package com.lzm.toolfx.controller;

import com.lzm.toolfx.common.Property;
import com.lzm.toolfx.module.aio.AioServer;
import com.lzm.toolfx.module.notiy.FakeSocket;
import com.lzm.toolfx.module.notiy.NotifyType;
import com.lzm.toolfx.module.notiy.SocketObserver;
import com.lzm.toolfx.utils.SysInfo;
import com.lzm.toolfx.utils.SystemPrint;
import de.felixroske.jfxsupport.FXMLController;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;

import java.io.PrintStream;
import java.net.URL;
import java.nio.channels.NotYetBoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

@FXMLController
public class LocationController implements Initializable, SocketObserver {

    @FXML
    private ListView socketList;        //已连接的Socket
    @FXML
    private TextField port;             //端口号TextField
    @FXML
    private ChoiceBox host;             //IP地址
    @FXML
    private Button quit ;               //退出按钮
    @FXML
    private Button start;               //开始连接按钮
    @FXML
    private TextArea log;               //控制台
    @FXML
    private Label socketSize;           //Label socket连接数
    @FXML
    private Label dataSize;             //Label socket传输字节大小
    @FXML
    private Label net;             //Label socket传输字节大小

    /*本机所有的IPv4地址*/
    private ObservableList ipList;
    /*重定向System.out()输出流*/
    private PrintStream printStream;
    /*Socket 服务*/
    private AioServer server;
    /*连接的 Socket 列表*/
    private List<FakeSocket> socketChannelList = new ArrayList<>();
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        start.setTooltip(new Tooltip("开始连接"));
        host.setTooltip(new Tooltip("本机IP列表"));
        port.setTooltip(new Tooltip("连接的端口号"));
        log.setEditable(false);
        log.setTooltip(new Tooltip("控制台"));
        //socketSize.setTooltip(new Tooltip("已连接的Socket设备"));
        //dataSize.setTooltip(new Tooltip("已接收的数据字节数 byte[n]"));
        ipList  = FXCollections.observableArrayList(SysInfo.getIpList());
        log.setStyle("-fx-text-fill: #5f5f5f");
        printStream = new SystemPrint(log);
        System.setOut(printStream);/*设置输出流*/
        Platform.runLater(()->{
            if(Property.showBanner){System.out.println(Property.BANNER + Property.VERSION);}
            System.out.println("——————————————————————本机信息———————————————————————\n" + SysInfo.getSystemInfo().getComputerSystem().getManufacturer());
            System.out.println(SysInfo.getSystemInfo().getProcessor()+"\n"+Property.dash);
        });
        initNet();
    }

    private void initNet(){
        port.setText(Property.server_port);
        host.setItems(ipList);
        host.setValue(ipList.get(0));//默认选择 index = 0 ->127.0.0.1

        //开始按钮点击事件，主要业务
        // 1.判断开始按钮状态
        // 2.检查数据库与消息队列
        // 3.开启服务
        start.setOnAction(event -> {
            socketChannelList.clear();
            updateList(FXCollections.observableArrayList(socketChannelList));
            if(start.getText().equals("开始")){
                LocationController temp = this;
                //新线程开启Server
                new Thread(){
                    @Override
                    public void run() {
                        super.run();
                        Platform.runLater(() ->{
                            //if(Property.isLock){
                            start.setStyle("-fx-background-color: #FF0000");
                            start.setText("停止");
                            start.setDisable(true);
                            port.setDisable(true);
                            host.setDisable(true);
                            //}
                        });
                        //initialize();
                        //if(Property.MQAvailable&&Property.DBAvailable){
                        server = new AioServer(temp,(String)host.getValue(),port.getText());
                        //server = new AioServer((String)host.getValue(),port.getText());
                        try {
                            Platform.runLater(()->{
                                if(!Property.isLock){
                                    start.setDisable(false);
                                    port.setDisable(true);
                                    host.setDisable(true);
                                }
                            });
                            server.start();
                        }catch (NotYetBoundException e){//异常处理
                            System.out.println("端口:"+port.getText()+" 可能已经被占用");
                            Platform.runLater(() ->{
                                start.setText("开始");
                                start.setStyle("-fx-background-color:  #354A5F");
                                start.setDisable(false);
                                port.setDisable(false);
                                host.setDisable(false);
                            });
                        }
                        catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        // }
                    }
                }.start();
            }else if(start.getText().equals("停止")&&server.isRun()&&!Property.isLock){
                Platform.runLater(() -> {
                    port.setDisable(false);
                    host.setDisable(false);
                    start.setStyle("-fx-background-color: #354A5F");
                    start.setText("开始");
                    server.stop();
                });
            }
        });
    }
    /**更新ListView的Cell*/
    public void updateList(ObservableList<FakeSocket> sockets){
        List<String> infos = new ArrayList<>();
        for(FakeSocket fakeSocket : sockets){
            infos.add(fakeSocket.ip +">byte["+fakeSocket.size+"]");//+ ">设备号:"+fakeSocket.getDeviceId()+">byte["+fakeSocket.size+"]"
        }
        Platform.runLater(() -> socketList.setItems(FXCollections.observableArrayList(infos) ));
    }
    public void setSocketSize(int size){
        Platform.runLater(()->{
            //socketSize.setText(String.valueOf(size));
        });
    }
    public void setDataSize(String size){
        Platform.runLater(()->dataSize.setText(size));
    }
    public void setNetSpeed(String speed){ Platform.runLater(()->net.setText(speed)); }

    @Override
    public void update(NotifyType type, Object message) {
        FakeSocket msg = (FakeSocket) message;
        switch (type){
            case SIZE: //更新byte[] size()
                //循环查找IP地址，set(i,msg)
                synchronized (this) {
                    //dataSize += msg.getSize();
                }
                for (int i = socketChannelList.size() - 1; i >= 0; i--) {
                    FakeSocket fakeSocket =  socketChannelList.get(i);
                    if (msg.ip.equals(fakeSocket.getIp())) {
                        socketChannelList.set(i,msg);
                    }
                }
                //setDataSize(String.format("%.2f",dataSize/1048576)+"Mb");
                updateList(FXCollections.observableArrayList(socketChannelList));
                break;
            case IS_CLOSE://Socket关闭
                for (int i = socketChannelList.size() - 1; i >= 0; i--) {
                    FakeSocket fakeSocket =  socketChannelList.get(i);
                    if (msg.ip.equals(fakeSocket.getIp())) {
                        //socketChannelList.set(i,msg);
                        socketChannelList.remove(i);
                    }
                }
                updateList(FXCollections.observableArrayList(socketChannelList));
                setSocketSize(socketChannelList.size());
                break;
            case IS_CONNECT://新Socket连接
                if(!socketChannelList.contains(msg)) {
                    socketChannelList.add(msg);
                }
                updateList(FXCollections.observableArrayList(socketChannelList));
                setSocketSize(socketChannelList.size());
                break;
        }
    }
}
